﻿using System;
using BP.Plugin.Monitor.Application.Common.Interfaces;
using Finbuckle.MultiTenant;
using Finbuckle.MultiTenant.Abstractions;
using Infrastructure.Tenant;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace BP.Plugin.Monitor.Infrastructure;

public class OnlineUserMonitorBackgroundService : BackgroundService
{
    private readonly IServiceScopeFactory _scopeFactory;
    private readonly TimeSpan _checkInterval = TimeSpan.FromSeconds(30); // 每30秒检查一次
    private readonly TimeSpan _offlineTimeout = TimeSpan.FromMinutes(1); // 超过1分钟算离线
    private readonly IMultiTenantStore<BoilerplateTenantInfo> _tenantStore;

    public OnlineUserMonitorBackgroundService(
        IServiceScopeFactory scopeFactory,
        IMultiTenantStore<BoilerplateTenantInfo> tenantStore)
    {
        _scopeFactory = scopeFactory;
        _tenantStore = tenantStore;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            var now = DateTime.UtcNow;

            var tenants = await _tenantStore.GetAllAsync();
            if (tenants != null) 
            {
                foreach (var tenant in tenants) 
                {
                    using var scope = _scopeFactory.CreateScope();
                    scope.ServiceProvider.GetRequiredService<IMultiTenantContextSetter>()
                        .MultiTenantContext = new MultiTenantContext<BoilerplateTenantInfo>()
                        {
                            TenantInfo = tenant
                        };

                    var threshold = DateTime.UtcNow - _offlineTimeout;
                    var db = scope.ServiceProvider.GetRequiredService<IMonitorDbContext>();
                    var offlineUsers = await db.OnlineUsers
                        .Where(u => u.IsOnline && u.LastActiveTime < threshold)
                        .ToListAsync(stoppingToken);

                    foreach (var user in offlineUsers)
                    {
                        user.IsOnline = false;
                        // 可选：触发 SSE/WS 通知用户下线
                    }

                    if (offlineUsers.Any())
                    {
                        await db.SaveChangesAsync(stoppingToken);
                    }
                }
            }

            await Task.Delay(_checkInterval, stoppingToken);
        }
    }
}
